'''
Created on 05.11.2011

@author: alex
'''

import io, os, hashlib, mimetypes, logging
import abstract, traceback



def joinPath(*parts):
	"""join path elements"""
	parts=filter(None, parts)
	if len(parts)==0:
		return u''
	if len(parts)==1:
		return parts[0]
	elif len(parts)==2:
		return parts[0].rstrip(os.path.sep)+os.path.sep+parts[1].lstrip(os.path.sep)
	else:
		result=parts[0].rstrip(os.path.sep)+os.path.sep
		for part in parts[1:-1]:
			result+=part.strip(os.path.sep)+os.path.sep
		result+=parts[-1].lstrip(os.path.sep)
		return result
		return '' 
	result=''

class Wrapper(abstract.Reader, abstract.Writer):
	def __init__(self, osFileName, mode):
		self._osFileName=osFileName
		self._stream=io.open(osFileName, mode)
	def setContentType(self, contentType):
		pass
	def getContentType(self):
		mimetype=mimetypes.guess_type(self._osFileName)[0]
		return mimetype if mimetype else 'application/octet-stream'
	def read(self, n=-1):
		return self._stream.read(n)
	def write(self, data):
		return self._stream.write(data)
	def close(self):
		self._stream.close()
		return os.path.getmtime(self._osFileName)

class LocalFS(abstract.FS):
	
	def __init__(self, rootDir):
		self._rootDir=rootDir

	def _fsPath2osPath(self, fsPath):
		return joinPath(self._rootDir, fsPath.replace('/', os.path.sep))
	
	def _osPath2fsPath(self, fsPath):
		return os.path.relpath(fsPath, self._rootDir).replace(os.path.sep, '/')

	def getRealmUrl(self):
		return 'file://'+os.path.normcase(os.path.normpath(os.path.abspath(self._rootDir)))
	
	def open(self, fileName, mode='rt'):
		try:
			return Wrapper(self._fsPath2osPath(fileName), mode)
		except IOError as e:
			raise
			logging.error(e)
			raise IOError('error opening %s'%fileName)

	def stamp(self, fileName):
		osFileName=self._fsPath2osPath(fileName)
		if os.path.exists(osFileName):
			try:
				return os.path.getmtime(osFileName)
			except IOError as e:
				raise IOError('unable to acces to file %s'%fileName)
		else:
			return None
	
	def hash(self, fileName):
		f=None
		try:
			f=io.open(self._fsPath2osPath(fileName), 'rb')
			sha1=hashlib.sha1()
			data=f.read(8190)
			while data:
				sha1.update(data)
				data=f.read()
			f.close()
			return sha1.hexdigest()
		except IOError:
			raise
		finally:
			if f: f.close()
	
	def delete(self, fileName):
		try:
			os.remove(self._fsPath2osPath(fileName))
		except IOError:
			raise
		
	def files(self):
		try:
			result={}
			for (root, dirs, files) in os.walk(self._rootDir):
				for f in files:
					# TODO: more sophisticated filename to unicode converter needed 
					osFullName=unicode(joinPath(root, f), 'utf8')
					fsFileName=self._osPath2fsPath(osFullName)
					# TODO: check if file exists
					modificationTime=os.path.getmtime(osFullName)
					result[fsFileName]=modificationTime
			return result
		except IOError:
			raise